#include "../Headers/tFormatter.hpp"
#include <sstream>
#include <iostream>
#include <iomanip>
#include <codecvt>

using namespace std;

TFormater::StrLikeU8::StrLikeU8(const std::vector<uint8_t>& newContent) {
	content = newContent;
}

TFormater::StrLikeU8::StrLikeU8(const std::string& newContent) {
	content.resize(newContent.length());
	memcpy(&content[0], newContent.c_str(), newContent.length());
}

TFormater::TFormater(std::string strIn) {
	buffer.content.resize(strIn.size());
	memcpy(buffer.content.data(), strIn.c_str(), buffer.content.size());
	offset = 0;
}

int TFormater::read(int size, std::string& strOut) {
	if (buffer.content.size() - offset < size) {
		return -1;
	}

	strOut.resize(size);
	//strOut[size] = '\0';
	memcpy(&strOut[0], buffer.content.data() + offset, size);
	offset += size;
	return buffer.content.size() - offset;
}

int TFormater::moveBy(int size) {
	if (buffer.content.size() - offset < size) {
		return -1;
	}
	offset += size;
	return buffer.content.size() - offset;
}

int TFormater::parseFltBetween(std::string pre, std::string post, float& fltOut) {
	StrLikeU8 preU8(pre), postU8(post);
	size_t preOffset = buffer.find(preU8, offset);
	if (preOffset == string::npos) {
		return -1;
	}
	size_t postOffset = buffer.find(postU8, preOffset);
	if (postOffset == string::npos) {
		return -1;
	}
	size_t start = preOffset + preU8.length();
	size_t end = postOffset - 1;
	vector<uint8_t> vec = buffer.substr(start, end - start + 1);
	vec.push_back('\0');
	fltOut = atof((char*)vec.data());
	offset = postOffset + postU8.length();

	return buffer.content.size() - offset;
}

void TFormater::indent(int num, std::string& content) {
	content.reserve(content.size() + num);
	for (int idx = 0; idx < num; idx++) {
		content.append(" ");
	}
}

std::string TFormater::indents(int num) {
	string ret;
	ret.reserve(num);
	for (int idx = 0; idx < num; idx++) {
		ret.append(" ");
	}
	return ret;
}

std::string TFormater::cleanStr(std::string strIn) {
	size_t start = string::npos, end = string::npos;
	for (int idx = 0; idx < strIn.length(); idx++) {
		if ((strIn[idx] != ' ') && (strIn[idx] != '\n') && (strIn[idx] != '\r')) {
			start = idx;
			break;
		}
	}
	for (int idx = strIn.length() - 1; idx >= start; idx--) {
		if ((strIn[idx] != ' ') && (strIn[idx] != '\n') && (strIn[idx] != '\r')) {
			end = idx;
			break;
		}
	}
	if (start < string::npos) {
		return strIn.substr(start, end - start + 1);
	}
	else {
		return "";
	}
}

size_t TFormater::StrLikeU8::length() {
	return content.size();
}
size_t TFormater::StrLikeU8::find_first_of(char c, size_t offset) {
	for (size_t idx = offset; idx < length(); idx++) {
		if (content[idx] == c) {
			return idx;
		}
	}
	return string::npos;
}
size_t TFormater::StrLikeU8::find_last_of(char c, size_t offset) {
	for (size_t idx = offset; idx >= 0; idx--) {
		if (content[idx] == c) {
			return idx;
		}
	}
	return string::npos;
}

std::vector<uint8_t> TFormater::StrLikeU8::substr(size_t offset, size_t count) {
	vector<uint8_t> ret;
	if (offset == string::npos || offset >= content.size()) {
		return ret;
	}
	if (count == string::npos) {
		count = content.size() - offset;
	}
	ret.resize(count);
	memcpy(&ret[0], &content[offset], count);

	return ret;
}

size_t TFormater::StrLikeU8::find(const std::vector<uint8_t>& searchContent, int offset) {
	if (searchContent.size() == 0) {
		return string::npos;
	}
	size_t pos = offset;
	while (pos != string::npos) {
		pos = find_first_of(searchContent[0], pos);
		if (pos != string::npos) {
			if (pos + searchContent.size() > length()) {
				return string::npos;
			}
			bool flagMatch = true;
			for (int idx = 1; idx < searchContent.size(); idx++) {
				if (searchContent[idx] != content[pos + idx]) {
					flagMatch = false;
					break;
				}
			}
			if (flagMatch) {
				return pos;
			}
			else {
				pos++;
			}
		}
	}

	return string::npos;
}

size_t TFormater::StrLikeU8::find(const StrLikeU8& searchContent, int offset) {
	return find(searchContent.content, offset);
}

size_t TFormater::StrLikeU8::compare(const std::vector<uint8_t>& compareContent) {
	if (length() != compareContent.size()) {
		return 1;
	}
	for (int idx = 0; idx < length(); idx++) {
		if (content[idx] != compareContent[idx]) {
			return 1;
		}
	}
	return 0;
}

std::string TFormater::makeSpaces(int count) {
	char* retStr = new char[count + 1];
	for (int idx = 0; idx < count; idx++) {
		retStr[idx] = ' ';
	}
	retStr[count] = '\0';
	string ret = retStr;
	delete[] retStr;
	return ret;
}

std::wstring TWFormater::makeSpaces(int count) {
	wchar_t* retStr = new wchar_t[count + 1];
	for (int idx = 0; idx < count; idx++) {
		retStr[idx] = L' ';
	}
	retStr[count] = L'\0';
	wstring ret = retStr;
	delete[] retStr;
	return ret;
}

std::wstring TWFormater::addJsonSlashes(std::wstring str) {
	wstring ret = L"";
	for (auto& c : str) {
		if (c == L'"') {
			str.push_back(L'\\');
			str.push_back(c);
		}
		else {
			str.push_back(c);
		}
	}
	ret.push_back(L'\0');
	return ret;
}

std::wstring TWFormater::removeDelims(const std::wstring src, const std::wstring delims) {
	wstring ret;
	ret.reserve(src.size());
	for (auto& c : src) {
		bool isDelim = false;
		for (const auto& delim : delims) {
			isDelim |= (c == delim);
		}
		if (!isDelim) {
			ret += c;
		}
	}
	return ret;
}

std::wstring TWFormater::toLower(std::wstring strIn) {
	for (auto& c : strIn) {
		c = towlower(c);
	}
	return strIn;
}

bool TFormater::isNumber(std::string input) {
	return (string::npos == input.find_first_not_of("0123456789."));
}

string TFormater::char2str(char input) {
	string ret = "1";
	ret[0] = input;
	return ret;
}

std::string TFormater::bool2str(bool input) {
	if (input)
		return "true";
	else
		return "false";
}

string TFormater::int2str(int input, int digiNum) {
	if (digiNum <= 0) {
		string s;
		stringstream ss(s);
		ss << input;
		return ss.str();
	}
	else {
		std::ostringstream oss;
		if (input >= 0) {
			oss << std::setfill('0') << std::setw(digiNum) << input;
		}
		else {
			oss << '-' << std::setfill('0') << std::setw(digiNum - 1) << -input;
		}
		return oss.str();
	}
}

wstring TWFormater::int2str(int input, int digiNum) {
	if (digiNum <= 0) {
		wstring s;
		wstringstream ss(s);
		ss << input;
		return ss.str();
	}
	else {
		std::wostringstream oss;
		if (input >= 0) {
			oss << std::setfill(L'0') << std::setw(digiNum) << input;
		}
		else {
			oss << L'-' << std::setfill(L'0') << std::setw(digiNum - 1) << -input;
		}
		return oss.str();
	}
}

wstring TWFormater::ints2str(int* vals, int valNum, int digiNum, wchar_t delim) {
	if (valNum <= 0)
		return L"";
	if (digiNum <= 0) {
		wstring s;
		wstringstream ss(s);
		for (int valIdx = 0; valIdx < valNum - 1; valIdx++) {
			ss << vals[valIdx] << delim;
		}
		ss << vals[valNum - 1];
		return ss.str();
	}
	else {
		std::wostringstream oss;
		for (int valIdx = 0; valIdx < valNum - 1; valIdx++) {
			if (vals[valIdx] >= 0) {
				oss << std::setfill(L'0') << std::setw(digiNum) << vals[valIdx];
			}
			else {
				oss << L'-' << std::setfill(L'0') << std::setw(digiNum - 1) << -vals[valIdx];
			}
			oss << delim;
		}
		if (vals[valNum - 1] >= 0) {
			oss << std::setfill(L'0') << std::setw(digiNum) << vals[valNum - 1];
		}
		else {
			oss << L'-' << std::setfill(L'0') << std::setw(digiNum - 1) << -vals[valNum - 1];
		}
		return oss.str();
	}
}

std::wstring TWFormater::ints2str(std::vector<std::vector<int>> vals, int digiNum) {
	wstring ret;

	for (auto& val : vals) {
		auto valStr = ints2str(val.data(), val.size(), digiNum);

		if (ret.length() == 0) {
			ret = valStr;
		}
		else {
			ret += L";" + valStr;
		}
	}

	return ret;
}

std::wstring TFormater::int2wstr(int input, int digiNum) {
	return TWFormater::int2str(input, digiNum);
}


std::string TFormater::ints2str(int* vals, int valNum, int digiNum, char delim) {
	if (valNum <= 0)
		return "";
	if (digiNum <= 0) {
		string s;
		stringstream ss(s);
		for (int valIdx = 0; valIdx < valNum - 1; valIdx++) {
			ss << vals[valIdx] << delim;
		}
		ss << vals[valNum - 1];
		return ss.str();
	}
	else {
		std::ostringstream oss;
		for (int valIdx = 0; valIdx < valNum - 1; valIdx++) {
			if (vals[valIdx] >= 0) {
				oss << std::setfill('0') << std::setw(digiNum) << vals[valIdx];
			}
			else {
				oss << '-' << std::setfill('0') << std::setw(digiNum - 1) << -vals[valIdx];
			}
			oss << delim;
		}
		if (vals[valNum - 1] >= 0) {
			oss << std::setfill('0') << std::setw(digiNum) << vals[valNum - 1];
		}
		else {
			oss << '-' << std::setfill('0') << std::setw(digiNum - 1) << -vals[valNum - 1];
		}
		return oss.str();
	}
}

string TFormater::ints2str(vector<int>& vals, int digiNum, char delim) {
	if (vals.size() > 0) {
		return ints2str(&vals[0], vals.size(), digiNum, delim);
	}
	else {
		return "";
	}
}

std::string TFormater::int2dArray2str(std::vector<std::vector<int>>& vals, int digiNum) {
	string ret = "[";
	for (vector<int>& array : vals) {
		string newArray = TFormater::ints2str(array, digiNum, ',');
		ret += "[" + newArray + "];";
	}
	ret += "]";
	return ret;
}

std::string TFormater::byte2hex(unsigned char val) {
	std::stringstream stream;
	stream << std::setfill('0') << std::setw(2) << std::hex << (unsigned long)val;
	//stream << std::hex << (int)val;
	string tempStr = stream.str();
	return tempStr.substr(tempStr.length() - 2, 2);
}

char TFormater::byte2hexChar(unsigned char val) {
	char ret;
	if (val <= 9) {
		ret = val + '0';
	}
	else {
		ret = (val - 10) + 'A';
	}
	return ret;
}

std::string TFormater::float2str(float input, int strLen, int digitAfterDot) {
	string s;
	stringstream ss(s);

	if (strLen > 0) {
		ss << setw(strLen);
	}
	if (digitAfterDot >= 0) {
		ss << fixed;
		ss << setprecision(digitAfterDot);
	}
	ss << input;
	return ss.str();
}

std::wstring TWFormater::float2str(float input, int strLen, int digitAfterDot) {
	wstring s;
	wstringstream ss(s);

	if (strLen > 0) {
		ss << setw(strLen);
	}
	if (digitAfterDot >= 0) {
		ss << fixed;
		ss << setprecision(digitAfterDot);
	}
	ss << input;
	return ss.str();
}

std::wstring TWFormater::floats2str(float* vals, int valNum, int strLen, int digitAfterDot, wchar_t delim) {
	if (valNum <= 0)
		return L"";

	wstring s;
	wstringstream ss(s);

	if (strLen > 0) {
		ss << setw(strLen);
	}
	if (digitAfterDot >= 0) {
		ss << fixed;
		ss << setprecision(digitAfterDot);
	}
	ss << vals[0];

	for (int idx = 1; idx < valNum; idx++) {
		ss << delim;
		if (strLen > 0) {
			ss << setw(strLen);
		}
		if (digitAfterDot >= 0) {
			ss << fixed;
			ss << setprecision(digitAfterDot);
		}
		ss << vals[idx];
	}
	return ss.str();
}

std::wstring TWFormater::float22str(float val0, float val1, int strLen, int digitAfterDot, wchar_t delim) {
	float vals[] = { val0, val1 };
	return floats2str(vals, 2, strLen, digitAfterDot, delim);
}

std::wstring TWFormater::float32str(float val0, float val1, float val2, int strLen, int digitAfterDot, wchar_t delim) {
	float vals[] = { val0, val1, val2 };
	return floats2str(vals, 3, strLen, digitAfterDot, delim);
}

std::wstring TWFormater::floats2str(std::vector<std::vector<float>> vals, int digiNum) {
	wstring ret;

	for (auto& val : vals) {
		auto valStr = floats2str(val.data(), (int)val.size(), -1, digiNum, L',');

		if (ret.length() == 0) {
			ret = valStr;
		}
		else {
			ret += L";" + valStr;
		}
	}

	return ret;
}

std::wstring TWFormater::formatCurrentDateTimeToString() {
	time_t     now = time(0);
	wchar_t       buf[256];
	struct tm now_time;
	localtime_s(&now_time, &now);

	// https://learn.microsoft.com/zh-cn/cpp/c-runtime-library/reference/strftime-wcsftime-strftime-l-wcsftime-l?view=msvc-170
	// for more information about date/time format
	wcsftime(buf, sizeof(buf), L"%Y_%m_%d_%H_%M_%S", &now_time);
	return wstring(buf);
}

std::wstring TWFormater::dateTime2FullStr(clock_t duration) {
	int seconds = duration / 1000;
	int minutes = seconds / 60;
	seconds = seconds - minutes * 60;
	int hours = minutes / 60;
	minutes = minutes - hours * 60;
	return dateTime2FullStr(hours, minutes, seconds);
}

std::wstring TWFormater::dateTime2FullStr(int hours, int minutes, int seconds) {
	return int2str(hours, 2) + L":" + int2str(minutes, 2) + L":" + int2str(seconds, 2);
}

std::wstring TWFormater::dateTime2ShortStr(int hours, int minutes, int seconds) {
	std::wstring ret;

	//bool firstSet = false;

	//if (hours > 0) {
	//	ret += TWFormater::int2str(hours);
	//	firstSet = true;
	//}

	//if (minutes > 0) {
	//	if (firstSet) {
	//		// unless hour is not set
	//		nD = -1;
	//	}
	//	else{
	//		ret += L":";
	//	}
	//	ret += TWFormater::int2str(minutes, nD);
	//	firstSet = true;
	//}

	//if (firstSet) {
	//	timeStr += L":";
	//}
	//timeStr += TWFormater::int2str(max(0, second), 2);

	return ret;
}

std::wstring TFormater::float2wstr(float input, int strLen, int digitAfterDot) {
	return TWFormater::float2str(input, strLen, digitAfterDot);
}

std::string TFormater::floats2str(float* vals, int valNum, int strLen, int digitAfterDot, char delim) {
	if (valNum <= 0)
		return "";

	string s;
	stringstream ss(s);

	if (strLen > 0) {
		ss << setw(strLen);
	}
	if (digitAfterDot >= 0) {
		ss << fixed;
		ss << setprecision(digitAfterDot);
	}
	ss << vals[0];

	for (int idx = 1; idx < valNum; idx++) {
		ss << delim;
		if (strLen > 0) {
			ss << setw(strLen);
		}
		if (digitAfterDot >= 0) {
			ss << fixed;
			ss << setprecision(digitAfterDot);
		}
		ss << vals[idx];
	}
	return ss.str();
}

string TFormater::floats2str(vector<float>& vals, int strLen, int digitAfterDot, char delim) {
	if (vals.size() > 0) {
		return floats2str(&vals[0], vals.size(), strLen, digitAfterDot, delim);
	}
	else {
		return "";
	}
}

string TFormater::float22str(float val0, float val1, int strLen, int digitAfterDot, char delim) {
	float tmp[2] = { val0,  val1 };
	return floats2str(tmp, sizeof(tmp) / sizeof(float), strLen, digitAfterDot, delim);
}

string TFormater::float32str(float val0, float val1, float val2, int strLen, int digitAfterDot, char delim) {
	float tmp[3] = { val0,  val1,  val2 };
	return floats2str(tmp, sizeof(tmp) / sizeof(float), strLen, digitAfterDot, delim);
}

string TFormater::float42str(float val0, float val1, float val2, float val3, int strLen, int digitAfterDot, char delim) {
	float tmp[4] = { val0,  val1,  val2,  val3 };
	return floats2str(tmp, sizeof(tmp) / sizeof(float), strLen, digitAfterDot, delim);
}

string TFormater::floats2str(int strLen, int digitAfterDot, char delim, int valNum, ...) {
	va_list valist;
	va_start(valist, valNum);

	string s;
	stringstream ss(s);

	if (strLen > 0) {
		ss << setw(strLen);
	}
	if (digitAfterDot >= 0) {
		ss << fixed;
		ss << setprecision(digitAfterDot);
	}
	ss << va_arg(valist, double);

	for (int idx = 1; idx < valNum; idx++) {
		ss << delim;
		if (strLen > 0) {
			ss << setw(strLen);
		}
		if (digitAfterDot >= 0) {
			ss << fixed;
			ss << setprecision(digitAfterDot);
		}
		ss << va_arg(valist, double);
	}
	return ss.str();
}

std::string TFormater::double2str(double input) {
	string s;
	stringstream ss(s);
	ss << input;
	return ss.str();
}

std::string TFormater::doubles2str(std::vector<double>& vals, int strLen, int digitAfterDot, char delim) {
	if (vals.size() <= 0)
		return "";
	string s;
	stringstream ss(s);

	if (strLen > 0) {
		ss << setw(strLen);
	}
	if (digitAfterDot >= 0) {
		ss << fixed;
		ss << setprecision(digitAfterDot);
	}
	ss << vals[0];

	for (int idx = 1; idx < vals.size(); idx++) {
		ss << delim;
		if (strLen > 0) {
			ss << setw(strLen);
		}
		if (digitAfterDot >= 0) {
			ss << fixed;
			ss << setprecision(digitAfterDot);
		}
		ss << vals[idx];
	}
	return ss.str();
}

std::string TFormater::formatCurrentDateTimeToString() {
	time_t     now = time(0);
	char       buf[128];
	struct tm now_time;
	localtime_s(&now_time, &now);

	// Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
	// for more information about date/time format
	strftime(buf, sizeof(buf), "%Y_%m_%d_%H_%M_%S", &now_time);
	return string(buf);
}

static string launchTime = TFormater::formatCurrentDateTimeToString();
std::string TFormater::formatLaunchDateTimeToString() {
	return launchTime;
}

int TFormater::str2int(const char* strIn) {
	return str2int(std::string(strIn));
}

int TWFormater::str2int(const wchar_t* strIn) {
	return str2int(std::wstring(strIn));
}

int TFormater::str2int(std::string strIn) {
	return std::stoi(strIn);
	//std::vector<std::string> subStrs = breakByPlusSign(strIn);
	//long long  sum = 0;
	//for (std::string str : subStrs) {
	//	sum += std::stoi(str);
	//}
	//return sum;
}

int TWFormater::str2int(std::wstring strIn) {
	return std::stoi(strIn);
	//std::vector<std::wstring> subStrs = breakByPlusSign(strIn);
	//long long  sum = 0;
	//for (std::wstring str : subStrs) {
	//	sum += std::stoi(str);
	//}
	//return sum;
}

int TFormater::str2int(std::wstring strIn) {
	return str2int(wstring2string(strIn));
}

vector<int> TFormater::str2ints(std::string strIn, char delim) {
	vector<string> valStrs = split(strIn, delim);
	vector<int> vals;
	for (string& valStr : valStrs) {
		if (valStr.length() > 0) {
			vals.push_back(str2int(valStr));
		}
	}
	return vals;
}

int TFormater::str2ints(std::string strIn, int* buffer, int maxNum, char delim) {
	vector<string> valStrs = split(strIn, delim);
	int num = min((int)valStrs.size(), maxNum);
	for (int idx = 0; idx < num; idx++) {
		*buffer++ = str2int(valStrs[idx]);
	}
	return num;
}

int TWFormater::str2ints(std::wstring strIn, int* buffer, int maxNum, char delim) {
	vector<wstring> valStrs = split(strIn, delim);
	int num = min((int)valStrs.size(), maxNum);
	for (int idx = 0; idx < num; idx++) {
		*buffer++ = str2int(valStrs[idx]);
	}
	return num;
}

std::vector<int> TWFormater::str2ints(std::wstring strIn, char delim, std::wstring removeChars) {
	if (removeChars.size() > 0) {
		wstring newStr;
		for (auto& c : strIn) {
			if (removeChars.find(c) == wstring::npos) {
				newStr.push_back(c);
			}
		}
		strIn = newStr;
	}
	std::vector<int> ret;
	vector<wstring> valStrs = split(strIn, delim);
	int num = (int)valStrs.size();
	for (int idx = 0; idx < num; idx++) {
		ret.push_back(str2int(valStrs[idx]));
	}
	return ret;
}

int TFormater::u82int(uint8_t* dat, int len) {
	char* content = new char[len + 1];
	memcpy(content, dat, len);
	content[len] = '\0';
	int ret = std::stoi(content);
	delete[] content;
	return ret;
}

long long TFormater::str2longlong(std::string strIn) {
	return std::stoll(strIn);
	//std::vector<std::string> subStrs = breakByPlusSign(strIn);
	//long long  sum = 0;
	//for (std::string str : subStrs) {
	//	sum += std::stoll(str.c_str());
	//}
	//return sum;
}

vector<long long> TFormater::str2longlongs(std::string strIn, char delim) {
	vector<string> valStrs = split(strIn, delim);
	vector<long long> vals;
	for (string& valStr : valStrs) {
		if (valStr.length() > 0) {
			vals.push_back(str2longlong(valStr));
		}
	}
	return vals;
}

double TFormater::str2double(const char* strIn) {
	return str2double(string(strIn));
}

double TFormater::str2double(std::string strIn) {
	return std::atof(strIn.c_str());
	//std::vector<std::string> subStrs = breakByPlusSign(strIn);
	//double sum = 0;
	//for (std::string str : subStrs) {
	//	sum += std::atof(str.c_str());
	//}
	//return sum;
}

double TWFormater::str2double(std::wstring strIn) {
	return _wtof(strIn.c_str());
	//std::vector<std::wstring> subStrs = breakByPlusSign(strIn);
	//double sum = 0;
	//for (std::wstring str : subStrs) {
	//	sum += _wtof(str.c_str());
	//}
	//return sum;
}

float TWFormater::formula2float(std::wstring strIn) {
	wstringstream iss(strIn);
	float num;
	wchar_t op;
	float result = 0;
	iss >> result;
	while (iss >> op) {
		if (iss >> num) {
			if (op == L'+') {
				result += num;
			}
			else if (op == L'-') {
				result -= num;
			}
			else if (op == L'*') {
				result *= num;
			}
			else if (op == L'/') {
				if (num == 0) {
					return 0;
				}
				result /= num;
			}
		}
	}

	return result;
}

std::vector<double> TFormater::str2doubles(std::string strIn, char delim) {
	vector<string> valStrs = split(strIn, delim);
	vector<double> vals;
	for (string& valStr : valStrs) {
		vals.push_back(str2double(valStr));
	}
	return vals;
}

float TFormater::str2float(const char* strIn) {
	return str2float(string(strIn));
}

float TFormater::str2float(string strIn) {
	return std::atof(strIn.c_str());
	//std::vector<std::string> subStrs = breakByPlusSign(strIn);
	//float sum = 0;
	//for (std::string str : subStrs) {
	//	sum += std::atof(str.c_str());
	//}
	//return sum;
}

bool TWFormater::charIsElementaryFormula(wchar_t ch) {
	if (ch == L'.') {
		return true;
	}
	if ((ch == L'+') || (ch == L'-') || (ch == L'*') || (ch == L'/')) {
		return true;
	}
	return (ch >= L'0') && (ch <= L'9');
}

bool TWFormater::strIsNumber(std::wstring strIn) {
	std::wstringstream ss(strIn);
	float temp;
	ss >> temp;
	return !ss.fail() && ss.eof();
}

float TWFormater::str2float(wstring strIn) {
	return _wtof(strIn.c_str());
	//std::vector<std::wstring> subStrs = breakByPlusSign(strIn);
	//float sum = 0;
	//for (std::wstring str : subStrs) {
	//	sum += _wtof(str.c_str());
	//}
	//return sum;
}

float TFormater::str2float(wstring strIn) {
	return str2float(wstring2string(strIn));
}

vector<float> TFormater::str2floats(std::string strIn, char delim) {
	vector<string> valStrs = split(strIn, delim);
	vector<float> vals;
	for (string& valStr : valStrs) {
		vals.push_back(str2float(valStr));
	}
	return vals;
}

vector<float> TWFormater::str2floats(std::wstring strIn, char delim) {
	vector<wstring> valStrs = split(strIn, delim);
	vector<float> vals;
	for (wstring& valStr : valStrs) {
		vals.push_back(str2float(valStr));
	}
	return vals;
}

std::vector<uint8_t> TWFormater::str2u8(std::wstring strIn) {
	string stdStr = TFormater::wstring2string(strIn);
	return TFormater::str2u8(stdStr);
}

vector<std::vector<int>> TWFormater::str2intVecs(std::wstring strIn) {
	vector<std::vector<int>> ret;
	auto vecStrs = split(strIn, L';');

	for (auto& vecStr : vecStrs) {
		auto vec = str2ints(vecStr);
		ret.push_back(vec);
	}

	return ret;
}

std::vector<std::vector<float>> TWFormater::str2floatVecs(std::wstring strIn) {
	vector<std::vector<float>> ret;
	auto vecStrs = split(strIn, L';');

	for (auto& vecStr : vecStrs) {
		auto vec = str2floats(vecStr);
		ret.push_back(vec);
	}

	return ret;
}

int TFormater::str2floats(std::string strIn, float* dtOut, int dtLen, char delim) {
	vector<string> valStrs = split(strIn, delim);
	int num = min(dtLen, (int)valStrs.size());
	for (int idx = 0; idx < num; idx++) {
		dtOut[idx] = str2float(valStrs[idx]);
	}

	return num;
}

bool TFormater::str2Bool(std::string strIn) {
	return strIn[0] == 't' || strIn[0] == 'T' || strIn[0] == 'y' || strIn[0] == 'Y';
}

std::vector<uint8_t> TFormater::str2u8(std::string strIn) {
	vector<uint8_t> ret;
	str2u8(strIn, ret);
	return ret;
}

void TFormater::str2u8(std::string strIn, std::vector<uint8_t>& u8VecInOut) {
	for (int idx = 0; idx < strIn.length(); idx++) {
		u8VecInOut.push_back(strIn[idx]);
	}
}

std::string TFormater::str2DigitStr(std::string strIn) {
	std::string ret;
	for (int idx = 0; idx < strIn.length(); idx++) {
		if (strIn[idx] == 0x0A) {
			ret += "\n";
		}
		else if (strIn[idx] < 32 || strIn[idx] >= 132) {
			ret += "?? ";
		}
		else {
			ret += TFormater::int2str(strIn[idx] - 32, 2) + " ";
		}
	}
	return ret;
}

std::vector<std::string> TFormater::breakByPlusSign(std::string strIn) {
	return split(strIn, '+');
}

std::vector<std::wstring> TWFormater::breakByPlusSign(std::wstring strIn) {
	return split(strIn, '+');
}

int TFormater::parseImagenameToTime(std::string filename) {
	int underScoreOffset = 0;
	int dotOffset = 0;
	underScoreOffset = filename.find('_');
	if (underScoreOffset == string::npos) {
		return -1;
	}
	dotOffset = filename.find('.', underScoreOffset);
	if (dotOffset == string::npos) {
		return -1;
	}
	string subString = filename.substr(underScoreOffset + 1, dotOffset - underScoreOffset - 1);
	int time = str2int(&subString[0]);
	return time;
}

std::wstring TWFormater::combine(std::wstring* strIn, int number, wchar_t delim) {
	wstring ret;

	if (number == 0) {
		return ret;
	}
	ret = strIn[0];
	for (int idx = 1; idx < number; idx++) {
		ret += delim + strIn[idx];
	}

	return ret;
}

std::wstring TWFormater::combine(std::wstring* strIn, int number, std::wstring delim) {
	wstring ret;

	if (number == 0) {
		return ret;
	}
	ret = strIn[0];
	for (int idx = 1; idx < number; idx++) {
		ret += delim + strIn[idx];
	}

	return ret;
}

vector<string> TFormater::split(string strIn, char sep) {
	vector<string> subStrs;
	int pos = 0;
	int lastPos = 0;
	for (; pos < strIn.size(); pos++) {
		if (strIn[pos] == sep) {
			subStrs.push_back(strIn.substr(lastPos, pos - lastPos));
			lastPos = pos + 1;
		}
	}
	if (lastPos < (int)strIn.length()) {
		subStrs.push_back(strIn.substr(lastPos));
	}
	return subStrs;
}

std::vector<std::wstring> TFormater::split(std::wstring strIn, wchar_t delim) {
	return TWFormater::split(strIn, delim);
}

std::vector<std::wstring> TWFormater::split(std::wstring strIn, wchar_t delim) {
	vector<wstring> subStrs;
	if (strIn.length() == 0) {
		return subStrs;
	}
	int pos = 0;
	int lastPos = 0;
	for (; pos < strIn.size(); pos++) {
		if (strIn[pos] == delim) {
			subStrs.push_back(strIn.substr(lastPos, pos - lastPos));
			lastPos = pos + 1;
		}
	}
	if (lastPos == (int)strIn.length()) {
		//subStrs.push_back(L"");
	}
	else if (lastPos < (int)strIn.length()) {
		subStrs.push_back(strIn.substr(lastPos));
	}
	return subStrs;
}

void TWFormater::append(std::wstring& strLong, std::wstring& strApp, std::wstring delim) {
	if (strLong.length() == 0) {
		strLong = strApp;
	}
	else {
		strLong.append(delim);
		strLong.append(strApp);
	}
}

std::vector<std::wstring> TWFormater::splitPlusMinus(std::wstring strIn) {
	vector<wstring> subStrs;
	if (strIn.length() == 0) {
		return subStrs;
	}
	int pos = 1;
	int lastPos = 0;
	for (; pos < strIn.size(); pos++) {
		if (strIn[pos] == L'+' || strIn[pos] == L'-') {
			//size_t start = max(0, lastPos - 1);
			subStrs.push_back(strIn.substr(lastPos, pos - lastPos));
			lastPos = pos;
		}
	}
	if (lastPos < (int)strIn.length()) {
		subStrs.push_back(strIn.substr(lastPos));
	}
	return subStrs;
}

vector<string> TFormater::splitVars(string strIn, char delim0, char delim1, vector<string>* interVarContentOut) {
	vector<string> ret;
	size_t interStart = 0;

	while (true) {
		size_t interEnd = strIn.find_first_of(delim0, interStart);
		if (interEnd == string::npos) {
			if (interVarContentOut != nullptr) {
				interVarContentOut->push_back(strIn.substr(interStart));
			}
			return ret;
		}
		else {
			if (interVarContentOut != nullptr) {
				interVarContentOut->push_back(strIn.substr(interStart, interEnd));
			}
		}
		size_t varStart = interEnd + 1;
		size_t varEnd = strIn.find_first_of(delim1, varStart);
		if (varEnd != string::npos) {
			ret.push_back(strIn.substr(varStart, varEnd - varStart));
			interStart = varEnd + 1;
		}
		else {
			cout << "Irregular format in var str [" + strIn + "]" << endl;;
			return ret;
		}
	}

	return ret;
}

vector<vector<uint8_t>> TFormater::splitVars(vector<uint8_t> strIn, char delim0, char delim1, vector<vector<uint8_t>>* interVarContentOut) {
	vector<vector<uint8_t>> ret;
	size_t interStart = 0;

	StrLikeU8 str(strIn);

	while (true) {
		size_t interEnd = str.find_first_of(delim0, interStart);
		if (interEnd == string::npos) {
			if (interVarContentOut != nullptr) {
				interVarContentOut->push_back(str.substr(interStart));
			}
			return ret;
		}
		else {
			if (interVarContentOut != nullptr) {
				interVarContentOut->push_back(str.substr(interStart, interEnd - interStart));
			}
		}
		size_t varStart = interEnd + 1;
		size_t varEnd = str.find_first_of(delim1, varStart);
		if (varEnd != string::npos) {
			ret.push_back(str.substr(varStart, varEnd - varStart));
			interStart = varEnd + 1;
		}
		else {
			cout << ("Irregular format in var u8str [" + toDisplayable(strIn) + "]") << endl;;
			return ret;
		}
	}

	return ret;
}

int TFormater::split(std::wstring strIn, std::wstring* strsOut, int maxNum, wchar_t delim) {
	return TWFormater::split(strIn, strsOut, maxNum, delim);
}

int TWFormater::split(std::wstring strIn, std::wstring* strsOut, int maxNum, wchar_t delim) {
	auto temp = split(strIn, delim);
	int num = min((int)temp.size(), maxNum);
	for (int idx = 0; idx < num; idx++) {
		strsOut[idx] = temp[idx];
	}
	return num;
}

std::string TFormater::getSubstrInBetween(std::string strIn, char from, char to) {
	int fromIdx = strIn.find_first_of(from) + 1;
	int toIdx = strIn.find_first_of(to, fromIdx);
	return strIn.substr(fromIdx, toIdx - fromIdx);
}

string TFormater::expandStrToSize(std::string strIn, int newSize) {
	if (strIn.length() >= newSize) {
		return strIn;
	}
	char* expStr = new char[newSize];

	memset(expStr, ' ', newSize);
	memcpy(expStr, &strIn[0], strIn.length());
	expStr[newSize - 1] = '\0';

	string ret = expStr;

	delete[] expStr;
	return ret;
}

bool TFormater::beginWith(std::wstring mainStr, std::wstring subString) {
	return TWFormater::beginWith(mainStr, subString);
}
bool TWFormater::beginWith(std::wstring mainStr, std::wstring subString, std::wstring* followingPartOut) {
	if (mainStr.length() < subString.length()) {
		return false;
	}
	for (int idx = 0; idx < subString.length(); idx++) {
		if (subString[idx] != mainStr[idx]) {
			return false;
		}
	}
	if (followingPartOut != nullptr) {
		*followingPartOut = mainStr.substr(subString.length());
	}
	return true;
}

bool TWFormater::endWith(std::wstring mainStr, std::wstring subString, std::wstring* leadingPartOut) {
	if (mainStr.length() < subString.length()) {
		return false;
	}
	for (int backOffset = 1; backOffset <= subString.length(); backOffset++) {
		if (subString[subString.length() - backOffset] != mainStr[mainStr.length() - backOffset]) {
			return false;
		}
	}
	return true;
}

bool TWFormater::between(std::wstring& mainStr, std::wstring start, std::wstring end, std::wstring& contentOut) {
	size_t startOffset = mainStr.find(start);
	if (startOffset == std::wstring::npos) {
		return false;
	}
	startOffset += start.length();

	size_t endOffset = mainStr.find(end, startOffset);
	if (endOffset == std::wstring::npos) {
		return false;
	}

	contentOut = mainStr.substr(startOffset, endOffset - startOffset);
	return true;
}

bool TFormater::beginWith(std::string mainStr, std::string subString) {
	if (mainStr.length() < subString.length()) {
		return false;
	}
	for (int idx = 0; idx < subString.length(); idx++) {
		if (subString[idx] != mainStr[idx]) {
			return false;
		}
	}
	return true;
}

bool TFormater::beginWith(std::vector<uint8_t> mainStr, std::string subString) {
	if (mainStr.size() < subString.length()) {
		return false;
	}
	for (int idx = 0; idx < subString.length(); idx++) {
		if (subString[idx] != mainStr[idx]) {
			return false;
		}
	}
	return true;
}

std::string TFormater::toDisplayable(std::string data, char delim) {
	return toDisplayable(&data[0], data.length(), delim);
}

std::string TFormater::toDisplayable(std::vector<uint8_t> data, char delim) {
	if (data.size() == 0) {
		return "";
	}
	return toDisplayable(&data[0], data.size(), delim);
}

std::string TFormater::toDisplayable(void* buffer, int length, char delim) {
	if (length > 0) {
		uint8_t* bufferRef = (uint8_t*)buffer;
		vector<char> result;
		for (int idx = 0; idx < length; idx++) {
			if (*bufferRef == '\0') {
				int stop = 1;
			}
			//if (*bufferRef >= 0x20 && *bufferRef <= 0x7E && *bufferRef != '\\') {
			if (*bufferRef >= 0x20 && *bufferRef <= 0x7E) {
				result.push_back(*bufferRef);
			}
			else if (*bufferRef == '\r') {
				result.push_back('\\');
				result.push_back('r');
			}
			else if (*bufferRef == '\n') {
				result.push_back('\\');
				result.push_back('n');
			}
			else {
				std::stringstream stream;
				stream << std::setfill('0') << std::setw(2) << std::hex << (uint16_t)(*bufferRef);
				string tempStr = stream.str();
				tempStr = string("0x") + tempStr.substr(tempStr.length() - 2, 2);
				for (char c : tempStr) {
					result.push_back(c);
				}
			}
			if (delim != '\0' && idx != length - 1) {
				result.push_back(delim);
			}
			bufferRef++;
		}
		result.push_back('\0');
		return string(&result[0]);
	}
	else {
		return "";
	}
}


std::string TFormater::clockT2str(clock_t timeIn, std::string delim, bool withMs) {
	int nMs = timeIn % CLOCKS_PER_SEC;
	timeIn /= CLOCKS_PER_SEC;
	int nSec = timeIn % 60;
	timeIn /= 60;
	int nMin = timeIn % 60;
	timeIn /= 60;
	int nHr = timeIn % 100;
	timeIn / 100;
	string ret = TFormater::int2str(nHr, 2);
	ret.append(delim);
	ret.append(TFormater::int2str(nMin, 2));
	ret.append(delim);
	ret.append(TFormater::int2str(nSec, 2));
	if (withMs) {
		ret.append(",");
		ret.append(TFormater::int2str(min(9999, (int)floor(nMs * 10000.0f / CLOCKS_PER_SEC)), 4));
	}
	return ret;
}

long TFormater::str2Seconds(std::wstring timeFormated) {
	return str2Seconds(TFormater::wstring2string(timeFormated));
}

long TFormater::str2Seconds(std::string timeFormated) {
	size_t firstBreak = timeFormated.find(':');
	if (firstBreak == string::npos) {
		return 0;
	}
	else {
		size_t secondBreak = timeFormated.find(':', firstBreak + 1);
		if (secondBreak == string::npos) {
			return 0;
		}
		string hourStr = timeFormated.substr(firstBreak - 2, 2);
		string minuteStr = timeFormated.substr(secondBreak - 2, 2);
		string secondStr = timeFormated.substr(secondBreak + 1, 2);
		long hour = str2int(hourStr);
		long minu = str2int(minuteStr);
		long sec = str2int(secondStr);
		return sec + 60 * (minu + 60 * hour);
	}
}

std::wstring TFormater::string2wstring(std::string strIn) {
	try
	{
		std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
		return converter.from_bytes(strIn);
	}
	catch (std::range_error& e)
	{
		size_t length = strIn.length();
		std::wstring result;
		result.reserve(length);
		for (size_t i = 0; i < length; i++)
		{
			result.push_back(strIn[i] & 0xFF);
		}
		return result;
	}
}

std::string TFormater::wstring2string(std::wstring strIn) {
	size_t length = strIn.length();
	std::string result;
	result.reserve(length);
	for (size_t i = 0; i < length; i++)
	{
		result.push_back(strIn[i] & 0xFF);
	}
	return result;
}

std::string TFormater::removeEoL(std::string strIn) {
	int offset = strIn.length();
	while (offset >= 0) {
		if (strIn[offset] == '\r' || strIn[offset] == '\n') {
			offset--;
		}
		else {
			return strIn.substr(0, offset + 1);
		}
	}
	return strIn;
}

string TFormater::formatFilenameWithIdx(string filenameFormat, int imgIdx) {
	int bufferLen = (int)filenameFormat.length() + 1024;
	char* temp = new char[filenameFormat.length() + 1024];
	sprintf_s(temp, bufferLen, &filenameFormat[0], imgIdx);
	string strOut(temp);
	free(temp);
	return strOut;
}

int TFormater::matchTemplates(const std::vector<uint8_t>& dataIn, const vector<vector<uint8_t>>& templates) {
	// not fully implemented
	for (int idx = 0; idx < templates.size(); idx++) {
		const vector<uint8_t>& _template = templates[idx];
		if (dataIn.size() == _template.size()) {
			bool allMatch = true;
			for (int offset = 0; (offset < dataIn.size()) && allMatch; offset++) {
				allMatch &= (dataIn[offset] == _template[offset]);
			}
			if (allMatch) {
				return idx;
			}
		}
	}
	return -1;
}

void TStrTools::subVectorOfStrings(std::vector<std::string>& stringsIn, std::vector<std::string>& stringsOut, int startIdx, int endIdx) {
	stringsOut.clear();
	if (endIdx == -1)
		endIdx = int(stringsIn.size() - 1);
	for (int idx = startIdx; idx <= min(endIdx, int(stringsIn.size() - 1)); idx++) {
		stringsOut.push_back(std::string(stringsIn[idx]));
	}
}

bool TStrTools::compareCharBuffers(void* buf0, int buf0Len, void* buf1, int buf1Len) {
	if (buf0Len != buf1Len) {
		return false;
	}
	uint8_t* buf0Ref = (uint8_t*)buf0, * buf1Ref = (uint8_t*)buf1;

	for (int idx = 0; idx < buf0Len; idx++) {
		if (*buf0Ref++ != *buf1Ref++) {
			return false;
		}
	}
	return true;
}

bool TStrTools::endWith(const string& strFull, const string& strShort) {
	if (strShort.length() > strFull.length())
		return false;
	const char* strShortPtr = &strShort[0];
	const char* strFullPtr = &strFull[0] + strFull.length() - strShort.length();
	for (int pos = 0; pos < strShort.length(); pos++) {
		if (strShortPtr[pos] != strFullPtr[pos])
			return false;
	}
	return true;
}


std::string TStrTools::splitFuncAndParas(std::string funcNameAndParas, std::vector<std::string>* parasOut) {
	string ret;
	size_t start = funcNameAndParas.find_first_of('(');
	size_t end = funcNameAndParas.find_last_of(')');
	if ((start == string::npos) || (end == string::npos)) {
		return ret;
	}

	ret = funcNameAndParas.substr(0, start);
	string parasStr = funcNameAndParas.substr(start + 1, end - start - 1);

	vector<string> paraList;
	size_t startPos = 0;
	bool isEnclosed = false;
	for (int pos = 0; pos < parasStr.length(); pos++) {
		if (isEnclosed) {
			if (parasStr[pos] == ']') {
				string newPara = parasStr.substr(startPos + 1, pos - startPos - 1);
				paraList.push_back(newPara);
				startPos = pos + 2;
				isEnclosed = false;
			}
		}
		else {
			if (parasStr[pos] == '[') {
				isEnclosed = true;
			}
			else if (parasStr[pos] == '#') {
				startPos = pos + 1;
			}
			else if (parasStr[pos] == ',') {
				string newPara = parasStr.substr(startPos, pos - startPos);
				paraList.push_back(newPara);
				startPos = pos + 1;
			}
		}
	}

	{
		string newPara = parasStr.substr(startPos);
		if (newPara.length() > 0) {
			paraList.push_back(newPara);
		}
	}

	if (parasOut != nullptr) {
		*parasOut = paraList;
	}

	//SLogger::writeLine("splitFuncAndParas");
	//SLogger::writeLine(ret);
	//SLogger::writeLine(parasStr);
	//for (string& para : paraList) {
	//	SLogger::writeLine(para);
	//}
	return ret;
}

int strMayBeHex2int(std::string valStr) {
	if (valStr.length() > 2 && valStr[0] == '0' && valStr[1] == 'x') {
		return TFormater::strHex2Val<int>(valStr);
	}
	else {
		return TFormater::str2int(valStr);
	}
}

static size_t matchVar(std::string reply, size_t startPos, int* valOut) {
	size_t valStartM1 = reply.find('{', startPos);
	if (valStartM1 == string::npos) {
		return string::npos;
	}
	size_t valStart = valStartM1 + 1;
	size_t valEnd = reply.find('}', valStart);
	if (valStart != string::npos && valEnd != string::npos) {
		string val0Str = reply.substr(valStart, valEnd - valStart);
		if (val0Str.length() == 1) {
			if (val0Str[0] >= '0' && val0Str[0] <= '9') {
				*valOut = val0Str[0] - '0';
			}
			else {
				*valOut = val0Str[0];
			}
		}
		else {
			*valOut = strMayBeHex2int(val0Str);
		}
		return valEnd;
	}
	else {
		return string::npos;
	}
}

bool TStrTools::parseStrForVars(std::string reply, std::string keyword,
	int* followedByVal0Out,
	int* followedByVal1Out,
	int* followedByVal2Out) {
	size_t pos = reply.find(keyword);
	if (pos == string::npos) {
		//TLogger::writeWarnning("LowerController::parseReplyMatch cannot find [" + keyword + "] in [" + reply + "]");
		return false;
	}
	else {
		if (followedByVal0Out != nullptr) {
			size_t val0End = matchVar(reply, pos, followedByVal0Out);
			if (val0End != string::npos) {
				if (followedByVal1Out != nullptr) {
					size_t val1End = matchVar(reply, val0End, followedByVal1Out);
					if (val1End != string::npos) {
						if (followedByVal2Out != nullptr) {
							size_t val2End = matchVar(reply, val1End, followedByVal2Out);
							if (val2End != string::npos) {
							}
							else {
								//SLogger::writeWarnning("LowerController::parseReplyMatch cannot third value in [" + reply + "]");
								return false;
							}
						}
					}
					else {
						//SLogger::writeWarnning("LowerController::parseReplyMatch cannot second value in [" + reply + "]");
						return false;
					}
				}
			}
			else {
				//SLogger::writeWarnning("LowerController::parseReplyMatch cannot first value in [" + reply + "]");
				return false;
			}
		}
		return true;
	}
}

bool TStrTools::parseStrForVarVec(std::string reply, std::string keyword,
	std::vector<int>& followedByValsOut) {
	size_t pos = reply.find(keyword);
	if (pos == string::npos) {
		//SLogger::writeWarnning("LowerController::parseReplyMatch cannot find [" + keyword + "] in [" + reply + "]");
		return false;
	}
	else {
		size_t valStartM1 = reply.find('{', pos + keyword.length());
		size_t valEndP1 = reply.find('}', valStartM1 + 1);
		if (valStartM1 == string::npos || valEndP1 == string::npos) {
			return false;
		}
		followedByValsOut = TFormater::str2ints(reply.substr(valStartM1 + 1, valEndP1 - valStartM1 - 2 + 1), ',');
		return true;
	}
}

TConvByte::TConvByte(uint8_t* byteSrc, size_t totalLenIn) {
	byteSrcOrigin = byteSrc;
	byteSrcRec = byteSrcOrigin;
	bytesProcessed = 0;
	totalLen = totalLenIn;
	localCounterReset();
}

TConvByte::TConvByte(vector<uint8_t>& byteStreamAllocated) {
	byteSrcOrigin = &byteStreamAllocated[0];
	byteSrcRec = byteSrcOrigin;
	bytesProcessed = 0;
	totalLen = byteStreamAllocated.size();
	localCounterReset();
}

void TConvByte::fromByte(int& dataDst) {
	fromByteCore<int>(dataDst);
}
void TConvByte::fromByte(int* dataPtr, int count) {
	fromByteCore<int>(dataPtr, count);
}

void TConvByte::fromByte(float& dataDst) {
	fromByteCore<float>(dataDst);
}
void TConvByte::fromByte(float* dataPtr, int count) {
	fromByteCore<float>(dataPtr, count);
}

void TConvByte::fromByte(double& dataDst) {
	fromByteCore<double>(dataDst);
}
void TConvByte::fromByte(char& dataDst) {
	fromByteCore<char>(dataDst);
}

void TConvByte::fromByte(uint8_t& dataDst) {
	fromByteCore<uint8_t>(dataDst);
}

void TConvByte::fromByte(size_t& dataDst) {
	fromByteCore<size_t>(dataDst);
}

void TConvByte::fromByte(int64_t& dataDst) {
	fromByteCore<int64_t>(dataDst);
}

bool TConvByte::skipBytes(int count) {
	byteSrcRec += count;
	bytesProcessed += count;
	localCounter += count;
	return true;
}

uint8_t TConvByte::tryIDTFlag() {
	return *((uint8_t*)byteSrcRec);
}

bool TConvByte::confirmIDTFlag(uint8_t expectedFlag) {
	uint8_t newFlagIn = readIDT();
	return newFlagIn == expectedFlag;
}

uint8_t* TConvByte::getRef() {
	return byteSrcRec;
}

void TConvByte::fromByte(vector<int>& dataDst) {
	for (int idx = 0; idx < dataDst.size(); idx++) {
		memcpy(&dataDst[idx], byteSrcRec, sizeof(int));
		byteSrcRec += sizeof(int);
		bytesProcessed += sizeof(int);
		localCounter += sizeof(int);
	}
}

void TConvByte::fromByteCopy(void* dstPtr, size_t count) {
	memcpy(dstPtr, byteSrcRec, count);
	byteSrcRec += count;
	bytesProcessed += count;
	localCounter += count;
}

void TConvByte::fromByte(unsigned short& dataDst) {
	fromByteCore<unsigned short>(dataDst);
}

void TConvByte::fromByte(short& dataDst) {
	fromByteCore<short>(dataDst);
}

uint8_t TConvByte::readIDT() {
	uint8_t thisIDT;
	fromByte(thisIDT);
	return thisIDT;
}

int TConvByte::readInt() {
	int thisInt;
	fromByte(thisInt);
	return thisInt;
}

short TConvByte::readShort() {
	short thisShort;
	fromByte(thisShort);
	return thisShort;
}

int64_t TConvByte::readInt64() {
	int64_t thisLong;
	fromByte(thisLong);
	return thisLong;
}

float TConvByte::readFloat() {
	float thisFloat;
	fromByte(thisFloat);
	return thisFloat;
}

size_t TConvByte::readSizeT() {
	size_t thisFloat;
	fromByte(thisFloat);
	return thisFloat;
}

bool TConvByte::toByte(short dataSrc, int offsetFromStart) {
	return toByteCore<short>(dataSrc, offsetFromStart);
}

bool TConvByte::toByte(int dataSrc, int offsetFromStart) {
	return toByteCore<int>(dataSrc, offsetFromStart);
}

bool TConvByte::toByte(int* dataPtr, int count) {
	return toByteCore<int>(dataPtr, count);
}

bool TConvByte::toByte(int64_t dataSrc, int offsetFromStart) {
	return toByteCore<int64_t>(dataSrc, offsetFromStart);
}

bool TConvByte::toByte(float dataSrc) {
	return toByteCore<float>(dataSrc);
}
bool TConvByte::toByte(float* dataPtr, int count) {
	return toByteCore<float>(dataPtr, count);
}
bool TConvByte::toByte(double dataSrc) {
	return toByteCore<double>(dataSrc);
}
bool TConvByte::toByte(double* dataPtr, int count) {
	return toByteCore<double>(dataPtr, count);
}
bool TConvByte::toByte(char dataSrc) {
	return toByteCore<char>(dataSrc);
}
bool TConvByte::toByte(uint8_t dataSrc) {
	return toByteCore<uint8_t>(dataSrc);
}
bool TConvByte::toByte(vector<int>& dataSrc) {
	if (bytesProcessed + sizeof(int) * dataSrc.size() > totalLen) {
		return false;
	}
	else {
		for (int idx = 0; idx < dataSrc.size(); idx++) {
			memcpy(byteSrcRec, &dataSrc[idx], sizeof(int));
			byteSrcRec += sizeof(int);
			bytesProcessed += sizeof(int);
			localCounter += sizeof(int);
		}
		return true;
	}
}

bool TConvByte::toByteCopy(void* srcPtr, size_t count) {
	if (bytesProcessed + count > totalLen) {
		return false;
	}
	else {
		memcpy(byteSrcRec, srcPtr, count);
		byteSrcRec += count;
		bytesProcessed += count;
		localCounter += count;
		return true;
	}
}

bool TConvByte::localCounterReset() {
	localCounter = 0;
	return true;
}

bool ProcS::setIntIfNotNullPtr(int val, int* ref) {
	return setIfNotNullPtr<int>(val, ref);
}

bool ProcS::setFltIfNotNullPtr(float val, float* ref) {
	return setIfNotNullPtr<float>(val, ref);
}

bool ProcS::setDbIfNotNullPtr(double val, double* ref) {
	return setIfNotNullPtr<double>(val, ref);
}

bool ProcS::setBoolIfNotNullPtr(bool val, bool* ref) {
	return setIfNotNullPtr<bool>(val, ref);
}